/*
 * Copyright 2025 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alibaba.cloud.ai.manus.mcp.model.vo;

import com.alibaba.cloud.ai.manus.mcp.service.McpStateHolderService;
import com.alibaba.cloud.ai.manus.tool.AbstractBaseTool;
import com.alibaba.cloud.ai.manus.tool.code.ToolExecuteResult;
import com.alibaba.cloud.ai.manus.tool.innerStorage.ISmartContentSavingService;
import com.alibaba.cloud.ai.manus.tool.innerStorage.SmartContentSavingService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.ai.tool.ToolCallback;

import java.util.Map;

public class McpTool extends AbstractBaseTool<Map<String, Object>> {

  private final ToolCallback toolCallback;

  private final ObjectMapper objectMapper;

  private String serviceNameString;

  private McpStateHolderService mcpStateHolderService;

  private ISmartContentSavingService smartContentSavingService;

  public McpTool(ToolCallback toolCallback, String serviceNameString, String planId,
                 McpStateHolderService mcpStateHolderService, ISmartContentSavingService smartContentSavingService,
                 ObjectMapper objectMapper) {
    this.toolCallback = toolCallback;
    this.objectMapper = objectMapper;
    this.serviceNameString = serviceNameString;
    this.currentPlanId = planId;
    this.mcpStateHolderService = mcpStateHolderService;
    this.smartContentSavingService = smartContentSavingService;
  }

  @Override
  public String getName() {
    return toolCallback.getToolDefinition().name();
  }

  @Override
  public String getDescription() {
    return toolCallback.getToolDefinition().description();
  }

  @Override
  public String getParameters() {
    return toolCallback.getToolDefinition().inputSchema();
  }

  @Override
  @SuppressWarnings("unchecked")
  public Class<Map<String, Object>> getInputType() {
    return (Class<Map<String, Object>>) (Class<?>) Map.class;
  }

  @Override
  public String getCurrentToolStateString() {
    McpState mcpState = mcpStateHolderService.getMcpState(currentPlanId);
    if (mcpState != null) {
      return mcpState.getState();
    }
    return "";
  }

  @Override
  public ToolExecuteResult run(Map<String, Object> inputMap) {
    // Convert Map to JSON string, as ToolCallback expects string input
    String jsonInput;
    try {
      jsonInput = objectMapper.writeValueAsString(inputMap);
    } catch (JsonProcessingException e) {
      return new ToolExecuteResult("Error: Failed to serialize input to JSON - " + e.getMessage());
    }

    String result = toolCallback.call(jsonInput, null);
    if (result == null) {
      result = "";
    }

    SmartContentSavingService.SmartProcessResult smartProcessResult = smartContentSavingService
      .processContent(currentPlanId, result, getName());
    result = smartProcessResult.getSummary();
    // Here we can store the result to McpStateHolderService
    McpState mcpState = mcpStateHolderService.getMcpState(currentPlanId);
    if (mcpState == null) {
      mcpState = new McpState();
      mcpStateHolderService.setMcpState(currentPlanId, mcpState);
    }
    mcpState.setState(result);

    return new ToolExecuteResult(result);
  }

  @Override
  public void cleanup(String planId) {
    mcpStateHolderService.removeMcpState(planId);
  }

  @Override
  public String getServiceGroup() {
    return serviceNameString;
  }

  @Override
  public boolean isSelectable() {
    return true;
  }

}
